"""Simplified factory for creating event system components."""

import logging
from typing import Any, Dict, Optional

# from learners.interfaces.event import EventType
from learners.events.config import EventConfig
from learners.events.emitters import DefaultEventEmitter, EventEmitter, NullEventEmitter
from learners.events.handlers import (
    ClassifierAlignmentHandler,
    PostTrainingHandler,
    LoggingEventHandler,
    LossTrackerHandler,
    MemoryMonitorHandler,
    ArchitectureAnalysisEventHandler,

)
from learners.events.manager import BaseEventManager

logger = logging.getLogger(__name__)


class EventSystemFactory:
    """Simplified factory for creating event system components."""

    @staticmethod
    def create_event_emitter(
        args: Dict[str, Any], learner_instance: Any
    ) -> EventEmitter:
        """
        Create an event emitter from EventConfig.

        Args:
            args: Dictionary containing "event_config" key with EventConfig object
            learner_instance: The learner instance that will use the emitter

        Returns:
            EventEmitter instance (either active or null)
        """
        # Get EventConfig from args - it should be an EventConfig object
        event_config = args.get("event_config")
        if not isinstance(event_config, EventConfig):
            raise ValueError(f"Expected EventConfig object, got {type(event_config)}")

        # Check if events are disabled
        if not event_config.enabled:
            logger.info("Events disabled, using NullEventEmitter")
            return NullEventEmitter()

        # Create event manager and configure handlers
        event_manager = BaseEventManager()
        EventSystemFactory._configure_handlers_from_config(event_manager, event_config)

        emitter = DefaultEventEmitter(event_manager, learner_instance)
        # Format handler information for better readability
        handlers = event_manager.get_handlers()
        handler_count = len(handlers)

        # Create a formatted string showing handler details
        if handler_count > 0:
            handler_info = "\n".join(
                [
                    f"  - {handler.__class__.__name__}: {[event.value for event in handler._events]}"
                    for handler in handlers
                ]
            )
            logger.info(
                f"Created {emitter.__class__.__name__} with {handler_count} handlers:\n"
                f"{handler_info}"
            )
        else:
            logger.info(f"Created {emitter.__class__.__name__} with no handlers")
        # logger.info(
        #     f"Created {emitter.__class__.__name__} with {len(event_manager.get_handlers())} handlers\n"
        #     + f"{event_manager.get_handlers()}"
        # )
        return emitter

    @staticmethod
    def _configure_handlers_from_config(
        event_manager: BaseEventManager, config: EventConfig
    ) -> None:
        """Configure event handlers from EventConfig."""
        for handler_config in config.handlers:
            if not handler_config.enabled:
                continue

            try:
                handler = EventSystemFactory._create_handler_from_config(handler_config)
                if handler:
                    # Register handler for specified events
                    # Events are already normalized to EventType in HandlerConfig.__post_init__
                    for event_type in handler_config.events:
                        event_manager.register(event_type, handler)
                        logger.debug(
                            f"Registered {handler.__class__.__name__} for {event_type.value}"
                        )
            except Exception as e:
                logger.error(f"Failed to create handler {handler_config.type}: {e}")

    @staticmethod
    def _create_handler_from_config(handler_config) -> Optional[Any]:
        """Create a handler instance from HandlerConfig."""
        handler_type = handler_config.type

        # Use registered handlers if available
        if handler_type in _HANDLER_REGISTRY:
            handler_class = _HANDLER_REGISTRY[handler_type]
            try:
                return handler_class(handler_config)
            except Exception as e:
                logger.error(
                    f"Failed to create registered handler '{handler_type}': {e}"
                )
                return None
        else:
            logger.error(f"Failed to create handler '{handler_type}'")
            return None


# Handler registry for extensibility
_HANDLER_REGISTRY = {}


def register_handler(name: str, handler_class) -> None:
    """Register a handler class for dynamic creation."""
    _HANDLER_REGISTRY[name] = handler_class
    logger.debug(f"Registered handler: {name}")


def create_handler(name: str, config: Dict[str, Any]) -> Optional[Any]:
    """Create a handler by name with given configuration."""
    if name not in _HANDLER_REGISTRY:
        logger.error(f"Handler '{name}' not registered")
        return None

    handler_class = _HANDLER_REGISTRY[name]
    try:
        return handler_class(**config)
    except Exception as e:
        logger.error(f"Failed to create handler '{name}': {e}")
        return None


# Register built-in handlers
register_handler("LoggingEventHandler", LoggingEventHandler)
register_handler("MemoryMonitorHandler", MemoryMonitorHandler)
register_handler("LossTrackerHandler", LossTrackerHandler)
register_handler("ClassifierAlignmentHandler", ClassifierAlignmentHandler)
register_handler("PostTrainingHandler", PostTrainingHandler)
register_handler("ArchitectureAnalysisEventHandler", ArchitectureAnalysisEventHandler)
